#include <linux/slab.h>
#include <linux/blkdev.h>
#include <linux/vmalloc.h>
+#include <linux/wait.h>
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/pgalloc.h>
int st_wr_req;
int st_oo_req;
- struct work_struct free_work;
+ wait_queue_head_t waiting_to_free;
grant_handle_t shmem_handle;
grant_ref_t shmem_ref;
} blkif_t;
-blkif_t *alloc_blkif(domid_t domid);
-void free_blkif_callback(blkif_t *blkif);
+blkif_t *blkif_alloc(domid_t domid);
+void blkif_free(blkif_t *blkif);
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);
#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
#define blkif_put(_b) \
do { \
if (atomic_dec_and_test(&(_b)->refcnt)) \
- free_blkif_callback(_b); \
+ wake_up(&(_b)->waiting_to_free);\
} while (0)
/* Create a vbd. */
static kmem_cache_t *blkif_cachep;
-blkif_t *alloc_blkif(domid_t domid)
+blkif_t *blkif_alloc(domid_t domid)
{
blkif_t *blkif;
atomic_set(&blkif->refcnt, 1);
init_waitqueue_head(&blkif->wq);
blkif->st_print = jiffies;
+ init_waitqueue_head(&blkif->waiting_to_free);
return blkif;
}
return 0;
}
-static void free_blkif(void *arg)
+void blkif_free(blkif_t *blkif)
{
- blkif_t *blkif = (blkif_t *)arg;
+ atomic_dec(&blkif->refcnt);
+ wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
/* Already disconnected? */
- if (blkif->irq) {
+ if (blkif->irq)
unbind_from_irqhandler(blkif->irq, blkif);
- blkif->irq = 0;
- }
vbd_free(&blkif->vbd);
if (blkif->blk_ring.sring) {
unmap_frontend_page(blkif);
free_vm_area(blkif->blk_ring_area);
- blkif->blk_ring.sring = NULL;
}
kmem_cache_free(blkif_cachep, blkif);
}
-void free_blkif_callback(blkif_t *blkif)
-{
- INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
- schedule_work(&blkif->free_work);
-}
-
void __init blkif_interface_init(void)
{
blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
if (be->blkif) {
if (be->blkif->xenblkd)
kthread_stop(be->blkif->xenblkd);
- blkif_put(be->blkif);
+ blkif_free(be->blkif);
be->blkif = NULL;
}
be->dev = dev;
dev->data = be;
- be->blkif = alloc_blkif(dev->otherend_id);
+ be->blkif = blkif_alloc(dev->otherend_id);
if (IS_ERR(be->blkif)) {
err = PTR_ERR(be->blkif);
be->blkif = NULL;
#include <linux/in.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/wait.h>
#include <xen/evtchn.h>
#include <xen/interface/io/netif.h>
#include <asm/io.h>
struct net_device *dev;
struct net_device_stats stats;
- struct work_struct free_work;
+ wait_queue_head_t waiting_to_free;
} netif_t;
#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
void netif_disconnect(netif_t *netif);
-netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]);
-void free_netif(netif_t *netif);
+netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]);
int netif_map(netif_t *netif, unsigned long tx_ring_ref,
unsigned long rx_ring_ref, unsigned int evtchn);
#define netif_put(_b) \
do { \
if ( atomic_dec_and_test(&(_b)->refcnt) ) \
- free_netif(_b); \
+ wake_up(&(_b)->waiting_to_free); \
} while (0)
void netif_xenbus_init(void);
.set_tx_csum = ethtool_op_set_tx_csum,
};
-netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
+netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
{
int err = 0, i;
struct net_device *dev;
netif->domid = domid;
netif->handle = handle;
netif->status = DISCONNECTED;
- atomic_set(&netif->refcnt, 0);
+ atomic_set(&netif->refcnt, 1);
+ init_waitqueue_head(&netif->waiting_to_free);
netif->dev = dev;
netif->credit_bytes = netif->remaining_credit = ~0UL;
return err;
}
-static void free_netif_callback(void *arg)
+static void netif_free(netif_t *netif)
{
- netif_t *netif = (netif_t *)arg;
+ atomic_dec(&netif->refcnt);
+ wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
if (netif->irq)
unbind_from_irqhandler(netif->irq, netif);
free_netdev(netif->dev);
}
-void free_netif(netif_t *netif)
-{
- INIT_WORK(&netif->free_work, free_netif_callback, (void *)netif);
- schedule_work(&netif->free_work);
-}
-
void netif_disconnect(netif_t *netif)
{
switch (netif->status) {
__netif_down(netif);
rtnl_unlock();
netif_put(netif);
- break;
+ /* fall through */
case DISCONNECTED:
- BUG_ON(atomic_read(&netif->refcnt) != 0);
- free_netif(netif);
+ netif_free(netif);
break;
default:
BUG();
if (be->netif == NULL) {
u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
- be->netif = alloc_netif(dev->otherend_id, handle, be_mac);
+ be->netif = netif_alloc(dev->otherend_id, handle, be_mac);
if (IS_ERR(be->netif)) {
err = PTR_ERR(be->netif);
be->netif = NULL;